This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

Try executing this chunk by clicking the Run button within the chunk or by placing your cursor inside it and pressing Ctrl+Shift+Enter.

Add a new chunk by clicking the Insert Chunk button on the toolbar or by pressing Ctrl+Alt+I.

When you save the notebook, an HTML file containing the code and output will be saved alongside it (click the Preview button or press Ctrl+Shift+K to preview the HTML file).

The preview shows you a rendered HTML copy of the contents of the editor. Consequently, unlike Knit, Preview does not run any R code chunks. Instead, the output of the chunk when it was last run in the editor is displayed.

require (ggplot2)
require(plotly)
Loading required package: plotly

Attaching package: <U+393C><U+3E31>plotly<U+393C><U+3E32>

The following object is masked from <U+393C><U+3E31>package:ggplot2<U+393C><U+3E32>:

    last_plot

The following object is masked from <U+393C><U+3E31>package:stats<U+393C><U+3E32>:

    filter

The following object is masked from <U+393C><U+3E31>package:graphics<U+393C><U+3E32>:

    layout
require(grid)
Loading required package: grid
require(ggthemes)
Loading required package: ggthemes
require (dplyr)
require(plyr)
Loading required package: plyr
--------------------------------------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
--------------------------------------------------------------------------------------------------------------

Attaching package: <U+393C><U+3E31>plyr<U+393C><U+3E32>

The following objects are masked from <U+393C><U+3E31>package:plotly<U+393C><U+3E32>:

    arrange, mutate, rename, summarise

The following objects are masked from <U+393C><U+3E31>package:dplyr<U+393C><U+3E32>:

    arrange, count, desc, failwith, id, mutate, rename, summarise, summarize
source ("theme_Publication.R")
cannot open file 'theme_Publication.R': No such file or directoryError in file(filename, "r", encoding = encoding) : 
  cannot open the connection

for Brownian motion

#Brownian motion (BM)
#1. make a data frame
BM <- data.frame (group= c("naked", "calcified"), rad= c(1.8E-6, 2.3E-6)) 
#2. calculate beta (beta)
BM$beta_s <- (2*(K*(10)^4)*Temp*(((BM$rad+Rehv)*100)^2))/((3*mu*10)*(BM$rad*Rehv*1e4)) #m3/s
BM$beta_d <- BM$beta_s*86400 #to cm3/day
# go back to this later
#3. calculate encounters (E)
BM$E <- BM$beta_d*hostnum
BM$E_HV <- BM$beta_d*virnum*hostnum
BM

Differential settling (DS)

#Differential settling (DS)
#1. read in PIC data
library(readr) #always use readr not baseR
setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
PIC <- read_csv("Postdoc-R/CSV Files/PIC.csv")
Parsed with column specification:
cols(
  Strain = col_character(),
  Replicate = col_integer(),
  TC = col_double(),
  AC = col_double(),
  Cellcount = col_double()
)
PIC$Strain <- as.factor(PIC$Strain)
PIC$Replicate <- as.factor(PIC$Replicate)
#certain changes in data.table API made calculating inside the list data.table to not work
#2. calculate PIC
PIC$PIC <- PIC$TC-PIC$AC
PIC$PICpercell <- (PIC$PIC/PIC$Cellcount)*(10)^-3#in g
PIC$PICpercellpg <- PIC$PICpercell*1e12
PIC$TCpg <- (PIC$TC/PIC$Cellcount)*(10)^-3*1e12 #what if total carbon is used for calculating density
ggplotly(ggplot(data=PIC, aes(x=Strain, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2) +theme_Publication())

ggplotly(ggplot(data=PIC, aes(x=Strain, y=TCpg)) + geom_boxplot()+geom_point(size=2) +theme_Publication())
#3. calculate density of cells (den)
PIC <- mutate(PIC, group = ifelse(PICpercellpg < 4 , "naked", "calcified"))
ggplotly(ggplot(data=PIC, aes(x=group, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2, aes(color=Strain))+
           theme_Publication())
plotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

PIC <- mutate(PIC, rad = ifelse(group == "naked" ,  1.8E-6,  2.3E-6)) #in m
PIC$volume <- (4/3)*pi*(PIC$rad*100)^3 #in cm3
PIC$Den_cell2 <- (PIC$TCpg*1e-12)/PIC$volume #g/cm3, if TC is used density, total density (below) becomes really big (i.e., max 2 g/cm3 which is not reasonable)
PIC$Den_cell <- PIC$PICpercell/PIC$volume #g/cm3
PIC$Den_celltotal <- PIC$Den_cell+Den_OcM
ggplotly(ggplot(data=PIC, aes(x=Strain, y=Den_celltotal, color=group)) + geom_boxplot()+geom_point(size=2) 
         +theme_Publication())
plotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

#some strains that are "naked" have PIC<2. I chose to ignore this since in the lm model I do not use
#strain as a factor, rather data is treated as a whole (e.g., no grouping)
#4. calculate sinking velocity of cells
PIC$SinkVel <- ((2*((PIC$rad*100)^2)*(981)*(PIC$Den_celltotal-Den_CH2O))/(9*(mu*10)))*864 #meter per day
#g is converted to per day, 864 is the one that converts cm/s to m/day
#plot sinking velocity vs calcification
ggplot(data=PIC, aes(x=PICpercellpg, y=SinkVel, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
    labs(y = expression("Sinking velocity"~("m"~day^-1)), x = expression("PIC"~cell^-1)) +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

#5. calculate sinkvel of viruses
Den_virus <- 1.09 #data from Ben D. fresh EhV-207 density. old density of EhV-207 is 1.19
Ehv_SinkVel <- ((2*((Rehv*100)^2)*(981)*(Den_virus-Den_CH2O))/(9*(mu*10)))*864  #equals to 0
#6. calculate beta kernels
PIC$beta_s <- pi*(((PIC$rad+Rehv)*100)^2)*(abs((PIC$SinkVel-Ehv_SinkVel)/864)) #in encounters cm3/s
PIC$beta_d <- PIC$beta_s*86400 #in cm3/day
Sinkvelbeta.plot<- ggplot(data=PIC, aes(x=SinkVel, y=beta_d, color=Strain, shape=group)) + geom_point(size=5)+
  theme_Publication()+
  labs(x = expression("Sinking velocity"~("m"~day^-1)), y = expression(beta~("Encounters" ~ cm^3~day^-1))) +
 scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")
Sinkvelbeta.plot #change ticks

ggplotly(Sinkvelbeta.plot)
geom_GeomLogticks() has yet to be implemented in plotly.
  If you'd like to see this geom implemented,
  Please open an issue with your example code at
  https://github.com/ropensci/plotly/issuesplotly.js does not (yet) support horizontal legend items 
You can track progress here: 
https://github.com/plotly/plotly.js/issues/53 

ggplotly(ggplot(data=PIC, aes(x=Strain, y=SinkVel)) + geom_boxplot()+theme_Publication())

ggplot(data=PIC, aes(x=PICpercellpg, y=beta_d, color=Strain)) + geom_point(size=5)+theme_Publication()+
  labs(y = expression(beta~("Encounters"~cm^3~day^-1)), x = expression("PIC"~cell^-1))  +
scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

#7. calculate beta and encounters
#beta are in cells cm3/ day then encounters are to cells/cm3 day
PIC$E_DS_HV <- (PIC$beta_d*virnum*hostnum)  #E calculated with Virus and Host (10:1 MOI)
PIC$E_DS_V <- (PIC$beta_d*virnum) #E calculated with Virus
#8. calculate for lith parameters
lithvol <- 3*1e-12 #in cm3, from CJ's paper
PIC$perlith <- PIC$PICpercell/20 #in g, assuming 20 liths attached
PIC$perlithpg <- PIC$perlith*1e12 #in pg
PIC$Denlith <- (PIC$perlith/lithvol) + Den_OcM #in g/cm3, with organic matter attached
rad_lith <- 2E-6 #in m radius
PIC$SinkVel_lith <- ((2*((rad_lith*100)^2)*(981)*(PIC$Denlith-Den_CH2O))/(9*(mu*10)))*864 #meter per day
PIC$beta_s_lith <- pi*(((rad_lith+Rehv)*100)^2)*(abs((PIC$SinkVel_lith-Ehv_SinkVel)/864)) #in encounters cm3/s
PIC$beta_d_lith <- PIC$beta_s_lith*86400 #in cm3/day
ggplot(data=PIC, aes(x=perlithpg, y=SinkVel_lith, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
  labs(y = expression("Sinking velocity"~("m"~day^-1)), x = expression("PIC"~lith^-1)) 

PIC$Elith_DS_HV <- (PIC$beta_d_lith*virnum*hostnum)  #E calculated with Virus and Host (10:1 MOI)
PIC$Elith_DS_V <- (PIC$beta_d_lith*virnum) #E calculated with Virus
require (dplyr)
PIC$group2 <- case_when(
  PIC$PICpercellpg <2  ~ "naked_bouyant",
  PIC$PICpercellpg >2 & PIC$PICpercellpg < 4 ~ "naked/calcified uncertain",
  PIC$PICpercellpg >4 & PIC$PICpercellpg < 10 ~ "moderately calcified",
  PIC$PICpercellpg >10 ~ "strongly calcified", 
  TRUE ~ as.character(PIC$PICpercellpg)
)
breaks <- 10^(-10:10)
ggplot(data=PIC, aes(x=SinkVel, y=E_DS_HV, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
 scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

ggplot(data=PIC, aes(x=SinkVel, y=E_DS_V, color=Strain, shape=group)) + geom_point(size=5)+theme_Publication()+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

ggplot(data=PIC, aes(x=SinkVel_lith, y=Elith_DS_V, color=Strain, shape=group)) + geom_point(size=5) + 
  theme_Publication() + scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=3),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l")

summary_DS <- ddply(PIC, .(Strain), summarize,  PICpercellpg=mean(PICpercellpg), perlithpg = mean(perlithpg), 
                    Den_celltotal = mean (Den_celltotal),
                    SinkVel=mean(SinkVel),beta_d=mean(beta_d), E_DS_V= mean(E_DS_V), E_DS_HV=mean(E_DS_HV),
                    SinkVel_lith=mean (SinkVel_lith), beta_d_lith=mean (beta_d_lith), Elith_DS_HV=mean (Elith_DS_HV),
                    Elith_DS_V=mean (Elith_DS_V))
summary_DS_bygroup <- ddply(PIC, .(group2), summarize,  PICpercellpg=mean(PICpercellpg), perlithpg = mean(perlithpg), 
                            Den_celltotal = mean (Den_celltotal),
                            SinkVel=mean(SinkVel),beta_d=mean(beta_d), E_DS_V= mean(E_DS_V), E_DS_HV=mean(E_DS_HV), 
                            SinkVel_lith=mean (SinkVel_lith), beta_d_lith=mean (beta_d_lith), 
                            Elith_DS_HV=mean (Elith_DS_HV), Elith_DS_V=mean (Elith_DS_V))
summary_DS
summary_DS_bygroup
setwd("D:/R program")
The working directory was changed to D:/R program inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
require(openxlsx)
write.xlsx(summary_DS, file = "Postdoc-R/Exported Tables/summary_DS.xlsx")
write.xlsx(summary_DS_bygroup, file = "Postdoc-R/Exported Tables/summary_DS_bygroup.xlsx")
#9. regression of PIC and sinkvel of cells and liths
#a. for cells
PIC_reg <- lm(SinkVel~PICpercellpg, data=PIC) #essentially perfect fit: summary may be unreliable haha
summary(PIC_reg)

Call:
lm(formula = SinkVel ~ PICpercellpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0115036 -0.0029329  0.0004329  0.0021756  0.0113796 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.0180085  0.0009620   18.72   <2e-16 ***
PICpercellpg 0.0177476  0.0001254  141.58   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.005175 on 44 degrees of freedom
Multiple R-squared:  0.9978,    Adjusted R-squared:  0.9978 
F-statistic: 2.004e+04 on 1 and 44 DF,  p-value: < 2.2e-16
plot(residuals.lm(PIC_reg))
layout(matrix(1:4,2,2))

plot(PIC_reg)

coef(PIC_reg)
 (Intercept) PICpercellpg 
  0.01800852   0.01774764 
# coef(PIC_reg)
#(Intercept) PICpercellpg 
#0.01800852   0.01774764 
cor(PIC$PICpercellpg, PIC$SinkVel)
[1] 0.9989042
#cor = 0.9989042
beta_reg <- lm(beta_d~PICpercellpg, data=PIC)
plot(residuals.lm(beta_reg))
coef(beta_reg)
 (Intercept) PICpercellpg 
1.639233e-07 3.243054e-07 
#coef(beta_reg)
# (Intercept) PICpercellpg 
#1.639233e-07 3.243054e-07
E_DS_HV_reg <- lm(E_DS_HV~PICpercellpg, data=PIC)
E_DS_V_reg <- lm(E_DS_V~PICpercellpg, data=PIC)
plot(residuals.lm(E_DS_HV_reg))
plot(residuals.lm(E_DS_V_reg))
coef(E_DS_HV_reg)
 (Intercept) PICpercellpg 
   0.8196165    1.6215272 
coef(E_DS_V_reg)
 (Intercept) PICpercellpg 
0.0008196165 0.0016215272 
#b. for liths
perlith_reg <- lm (perlithpg~PICpercellpg, data=PIC)
plot(resid(perlith_reg))

coef(perlith_reg)
  (Intercept)  PICpercellpg 
-6.547738e-17  5.000000e-02 
sinkvel_lith_reg <- lm(SinkVel_lith~PICpercellpg, data = PIC)
summary(sinkvel_lith_reg)
essentially perfect fit: summary may be unreliable

Call:
lm(formula = SinkVel_lith ~ PICpercellpg, data = PIC)

Residuals:
       Min         1Q     Median         3Q        Max 
-1.043e-16 -3.686e-17 -2.422e-18  4.040e-17  7.364e-17 

Coefficients:
              Estimate Std. Error   t value Pr(>|t|)    
(Intercept)  1.673e-02  8.512e-18 1.965e+15   <2e-16 ***
PICpercellpg 1.115e-02  1.109e-18 1.005e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.579e-17 on 44 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 1.011e+32 on 1 and 44 DF,  p-value: < 2.2e-16
plot(residuals.lm(sinkvel_lith_reg))
layout(matrix(1:4,2,2))

plot(sinkvel_lith_reg)

coef(sinkvel_lith_reg)
 (Intercept) PICpercellpg 
  0.01672753   0.01115169 
beta_lith_reg <- lm(beta_d_lith~PICpercellpg, data=PIC)
plot(residuals.lm(beta_lith_reg))
coef(beta_lith_reg)
 (Intercept) PICpercellpg 
2.302277e-07 1.528542e-07 
Elith_DS_HV_reg <- lm(Elith_DS_HV~PICpercellpg, data=PIC)
Elith_DS_V_reg <- lm(Elith_DS_V~PICpercellpg, data=PIC)
plot(residuals.lm(Elith_DS_HV_reg))
plot(residuals.lm(Elith_DS_V_reg))

coef(Elith_DS_HV_reg)
 (Intercept) PICpercellpg 
    1.151139     0.764271 
coef(Elith_DS_V_reg)
 (Intercept) PICpercellpg 
 0.001151139  0.000764271 
# 9. make new dataframe depending on experimental PIC values
# make a prediction based on PIC values
require(truncnorm)
require(Rmisc)
summary(PIC$PICpercellpg)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-1.5873  0.5523  2.3009  4.6739  6.1204 20.1442 
summarySE(data=PIC, measurevar="PICpercellpg")
PIC_newdata <- as.data.frame(rtruncnorm(n=1000, a=-1.6, b=20.14, mean=4.7, sd=6.15))
#rename column. rename function in plyr 
library(plyr)
PIC_newdata <- rename (PIC_newdata, c ("rtruncnorm(n = 1000, a = -1.6, b = 20.14, mean = 4.7, sd = 6.15)" = 
                                         "PICpercellpg"))
PIC_newdata <- mutate(PIC_newdata, group = ifelse(PICpercellpg < 4 , "naked", "calcified"))
ggplotly(ggplot(data=PIC_newdata, aes(x=group, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2) +
           theme_Publication())

PIC_newdata$group2 <- case_when(
  PIC_newdata$PICpercellpg <2  ~ "naked_bouyant",
  PIC_newdata$PICpercellpg >2 & PIC_newdata$PICpercellpg < 4 ~ "naked/calcified uncertain",
  PIC_newdata$PICpercellpg >4 & PIC_newdata$PICpercellpg < 10 ~ "moderately calcified",
  PIC_newdata$PICpercellpg >10 ~ "strongly calcified", 
  TRUE ~ as.character(PIC_newdata$PICpercellpg)
)
PIC_newdata$group2 <- factor (PIC_newdata$group2,levels= c("naked_bouyant", "naked/calcified uncertain",
                                                       "moderately calcified", "strongly calcified"),
                                                       labels = c("naked", "naked/calcified uncertain",
                                                                  "moderately calcified", "strongly calcified"))
ggplotly(ggplot(data=PIC_newdata, aes(x=group2, y=PICpercellpg)) + geom_boxplot()+geom_point(size=2)
         +theme_Publication())

#a. for host
PIC_newdata$SinkVel.pred <- predict(PIC_reg, data.frame(PIC_newdata))
PIC_newdata_reg <- lm(SinkVel.pred~PICpercellpg, data=PIC_newdata) 
coef(PIC_newdata_reg)
 (Intercept) PICpercellpg 
  0.01800852   0.01774764 
#same coef as PIC_reg
#> coef(PIC_newdata_reg)
#(Intercept) PICpercellpg 
#0.01800852   0.01774764 
plot(resid(PIC_newdata_reg))

ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=SinkVel.pred)) +geom_point(size=2) +theme_Publication()+
  labs(y = expression("Predicted Sinking velocity"~("m"~day^-1)), x = expression("PIC"~cell^-1)) 

PIC_newdata$beta.pred <- predict(beta_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_V.pred <- predict(E_DS_V_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_HV.pred <- predict(E_DS_HV_reg, data.frame(PIC_newdata))
ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_V.pred)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("PIC"~cell^-1)) +
  theme(legend.title = element_blank())

ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_HV.pred)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ cm^-3~day^-1), x = expression("PIC"~cell^-1)) +
  theme(legend.title = element_blank())

PICbeta_new <- ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=beta.pred)) +
  geom_point(size=5, aes(color=PICpercellpg))+
  scale_colour_gradient(name="PIC", guide=guide_colorbar(direction = "vertical", barheight=10))+
  theme_Publication() + 
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
  labs(y = expression(beta~("Predicted Encounters"~cm^3~day^-1)), x = expression("PIC"~cell^-1))+
  theme(legend.position = "right")
PICbeta_new

#b. for liths
PIC_newdata$perlithpg.pred <- predict(perlith_reg, data.frame(PIC_newdata))
PIC_newdata$SinkVel.pred.lith <- predict(sinkvel_lith_reg, data.frame(PIC_newdata))
sinkvel_lith_reg.pred <- lm(SinkVel.pred.lith~PICpercellpg, data=PIC_newdata) 
coef(sinkvel_lith_reg.pred)
 (Intercept) PICpercellpg 
  0.01672753   0.01115169 
#same coef as sinkvel_lith_reg
#> coef(sinkvel_lith_reg.pred)
#(Intercept) PICpercellpg 
# 0.01672753   0.01115169 
plot(resid(sinkvel_lith_reg.pred))

ggplot(data=PIC_newdata, aes(x=perlithpg.pred, y=SinkVel.pred.lith)) +geom_point(size=2) +theme_Publication()+
  labs(y = expression("Predicted Sinking velocity of Liths"~("m"~day^-1)), x = expression("PIC"~lith^-1)) 

PIC_newdata$beta.pred.lith <- predict(beta_lith_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_V.pred.lith <- predict(Elith_DS_HV_reg, data.frame(PIC_newdata))
PIC_newdata$E_DS_HV.pred.lith <- predict(Elith_DS_HV_reg, data.frame(PIC_newdata))
ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_V.pred.lith)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("PIC"~lith^-1)) +
  theme(legend.title = element_blank())

ggplot(data=PIC_newdata, aes(x=PICpercellpg, y=E_DS_HV.pred.lith)) +geom_point(size=5, aes(color=group2)) +
    theme_Publication() + geom_smooth() +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
    labs(y = expression("viral encounters " ~ cm^-3~day^-1), x = expression("PIC"~lith^-1)) +
  theme(legend.title = element_blank())

PICbeta_new.lith <- ggplot(data=PIC_newdata, aes(x=perlithpg.pred, y=beta.pred.lith)) +
  geom_point(size=5, aes(color=PICpercellpg))+
  scale_colour_gradient(name="PIC", guide=guide_colorbar(direction = "vertical", barheight=10))+
  theme_Publication() + 
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) + annotation_logticks(sides="l") +
  labs(y = expression(beta~("Predicted Encounters of lith " ~cm^3~day^-1)), x = expression("PIC"~lith^-1))+
  theme(legend.position = "right")
PICbeta_new.lith

#summaries
summary_DS_newdata_bygroup2 <- ddply(PIC_newdata, .(group2), summarize,  PICpercellpg=mean(PICpercellpg), SinkVel.pred=mean(SinkVel.pred),beta.pred= mean (beta.pred), E_DS_V.pred= mean(E_DS_V.pred), E_DS_HV.pred=mean(E_DS_HV.pred))
summary_DS_bygroup.pred <- ddply(PIC_newdata, .(group2), summarize,  PICpercellpg=mean(PICpercellpg), 
                            perlithpg.pred = mean(perlithpg.pred), SinkVel.pred=mean(SinkVel.pred),
                            beta.pred= mean (beta.pred), E_DS_V.pred= mean(E_DS_V.pred), 
                            E_DS_HV.pred=mean(E_DS_HV.pred), 
                            SinkVel.pred.lith=mean(SinkVel.pred.lith),beta.pred.lith= mean (beta.pred.lith),
                            E_DS_V.pred.lith= mean(E_DS_V.pred.lith), E_DS_HV.pred.lith=mean(E_DS_HV.pred.lith))
summary_DS_bygroup.pred
write.xlsx(summary_DS_bygroup.pred, file = "Postdoc-R/Exported Tables/summary_DS_bygroup.pred.xlsx")
cannot create file 'Postdoc-R/Exported Tables/summary_DS_bygroup.pred.xlsx', reason 'No such file or directory'

turbulence

#TURBULENCE
#disrate is cm2/s3
#make data frame
disrate <- rep_len(10^(-8:-2), length.out=14)
calc <- rep_len(c("calcified"), length.out=7)
naked <- rep_len(c("naked"), length.out=7)
lith <- rep_len(c("lith"), length.out=7)
group <- c(calc, naked, lith)
turb <- as.data.frame(cbind(disrate, group))
number of rows of result is not a multiple of vector length (arg 1)
turb$rad <- case_when(
    turb$group =="naked" ~ 1.8E-6,
    turb$group =="calcified" ~ 2.3E-6,
    turb$group =="lith" ~ 2E-6,
    TRUE ~ as.numeric(turb$group)
)
#turb <- mutate(turb, rad = ifelse(group == "naked" ,  1.8E-6,  2.3E-6)) #in m
turb$disrate <- as.numeric(as.character(turb$disrate))
turb$Kol <- ((v^3/turb$disrate)^0.25)*100 #Kolmogorov length scale in cm
#everything is below 1 cm, use eqn 2 in TK 
turb$beta_d <- (4.2*pi*((turb$disrate/(v*100^2))^0.5)*(((turb$rad+Rehv)*100)^3))*86400 
turb$beta_Heidi <- (0.42*pi*((turb$disrate/(v*100^2))^0.5)*(((turb$rad+Rehv)*100)^3))*86400
#check encounters
#use TK, in cm3 s
turb$E_turb_HV <- (turb$beta_d*hostnum*virnum) #E calculated with Virus and Host (10:1 MOI)
turb$E_turb_V <- (turb$beta_d*virnum) #E calculated with virus only
#breaks <- 10^(-10:10)
#minor_breaks <- rep(1:9, 21)*(10^rep(-10:10, each=9))
ggplot(data = turb, aes(x = disrate, y = beta_d, color=group)) + geom_point(size =5) +
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks() +
  theme_Publication() +
  labs(y = expression(beta~("predicted encounters " ~cm^3~day^-1)), 
       x = expression("dissipation rate "~(m^2~s^-3))) +
   theme(legend.title = element_blank())

  
library(scales)
ggplot(data = turb, aes(x = disrate, y = E_turb_V, color=group)) + geom_point(size =5) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication()+
  labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

ggplot(data = turb, aes(x = disrate, y = E_turb_HV, color=group)) + geom_point(size =5) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication()+
  labs(y = expression("viral encounters " ~ cm^-3~day^-1),x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

add beta kernels and plot

#extract mean betas from PIC_newdata
beta_DS <- summarySE (PIC_newdata, measurevar = "beta.pred", groupvars = c("group", "group2"))
lith_DS <-summarySE (PIC_newdata, measurevar = "beta.pred.lith", groupvars = c("group", "group2"))
lith_DS$group1 <- lith_DS$group
lith_DS$group <- "lith"
#separate data frames for host and liths
all <- Reduce(function(x,y) merge(x,y,by="group",all=TRUE) ,
              list(BM, beta_DS, turb %>% filter(group %in% c("naked", "calcified"))))
all.liths  <- Reduce(function(x,y) merge(x,y,by="group",all=TRUE) ,
                     list(lith_DS, turb %>% filter(group %in% c("lith"))))
#beta_d.x=BM, beta.pred=DS, betapred.lith= beta.pred.lith, beta_d.y=turb
#rename beta.pred to beta_pred so I can use grep. 
#all <- rename (all, c("beta_d.x" = "beta_BM", "beta.pred" = "beta_DS", "beta_d.y" = "beta_turb"))
library(data.table)
NT = data.table(all, key="group2")
allbetas = NT[, list(group=group, disrate=disrate, beta_BM=beta_d.x, beta_DS=beta.pred, beta_turb = beta_d.y, 
                     beta_BM_DS =beta_d.x + beta.pred,
                     beta_DS_turb = beta.pred + beta_d.y,
                     beta_BM_turb = beta_d.x + beta_d.y,
                     beta_all = beta_d.x + beta_d.y + beta.pred), 
              by=c("group2")]
NT2 <- data.table(all.liths, key = "group2")
allbetas.lith = NT2[, list(group=group, group1=group1, disrate=disrate, beta_DS.lith=beta.pred.lith, 
                          beta_turb.lith = beta_d, 
                     beta_DS_turb.lith =beta.pred.lith + beta_d), 
                     by=c("group2")]
ggplot(allbetas, aes(disrate, y = value, color=group2)) + 
    geom_line(aes(y = beta_DS_turb, linetype = "DS+turb"), size=1) + 
    geom_line(aes(y = beta_all, linetype = "BM+DS+turb"), size=1)+
    geom_line(aes(y = beta_turb, linetype = "turb"), size=1)+
    geom_line(data = allbetas.lith, aes(y= beta_DS_turb.lith, linetype="DS+turb.lith")) +
    scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
    scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
    annotation_logticks()+
    theme_Publication() +
    theme(legend.title = element_blank(), legend.key.width=unit(2,"cm"))+
    guides(linetype=guide_legend(nrow  =4), colour=guide_legend(nrow=4,byrow=TRUE)) 

ggplot(allbetas, aes(disrate, y = value, color=group2)) + 
  geom_line(aes(y = beta_DS_turb, linetype = "DS+turb"), size=1) + 
  geom_line(data = allbetas.lith, aes(y= beta_DS_turb.lith, linetype="DS+turb.lith")) + 
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication() +
  theme(legend.title = element_blank(), legend.key.width=unit(2,"cm"))+
  guides(linetype=guide_legend(nrow  =4), colour=guide_legend(nrow=4,byrow=TRUE)) 

#encounters
#melt data
allbetas.melt <- melt (allbetas, id.vars = c("group2", "group", "disrate"), value.name = "beta_d", 
                       variable.name = "betakernel")
allbetas.melt$E_V <- allbetas.melt$beta_d*virnum
allbetas.melt$E_HV <- allbetas.melt$beta_d*virnum*hostnum
allbetas.melt.lith <- melt (allbetas.lith, id.vars = c("group2", "group1", "group", "disrate"), 
                            value.name = "beta_d", variable.name = "betakernel")
allbetas.melt.lith$E_V <- allbetas.melt.lith$beta_d*virnum
allbetas.melt.lith$E_HV <- allbetas.melt.lith$beta_d*virnum*hostnum
ggplot(allbetas.melt, aes(disrate, y = E_V, color=group2)) + 
  geom_line(size=1)+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks() + facet_grid(~betakernel)

#subset data
graph1 <- subset(allbetas.melt, betakernel %in% c ("beta_BM", "beta_DS", "beta_BM_DS"))
graph2 <- subset(allbetas.melt, betakernel %in% c ("beta_turb", "beta_DS_turb", "beta_BM_turb", "beta_all"))
lith <- subset(allbetas.melt.lith, betakernel %in% c("beta_DS_turb.lith") & group1 %in% c("calcified"))
lith$maingroup <- lith$group2
lith$group2 <- as.factor(paste(lith$maingroup, lith$group, sep='-'))
ggplot(graph1, aes(group2, y = E_V, color=betakernel)) + 
  geom_jitter(size=5)+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks(sides = "l")+
  theme_Publication() +
  labs(y = expression("viral encounters " ~ day^-1~cell^-1)) +
  theme(legend.title = element_blank())

graph1.sum <- summarySE (graph1, measurevar = "E_V", groupvars = c("betakernel", "group2"))
ggplot(graph1.sum, aes(group2, y = E_V, color=betakernel)) + 
  geom_point(size=5,  position=position_dodge(0.2))+
  scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks(sides = "l")+
  theme_Publication() +
  labs(y = expression("viral encounters " ~ day^-1~cell^-1)) +
  theme(legend.title = element_blank())

  
ggplot(data=allbetas.melt %>% filter(betakernel %in% c("beta_turb", "beta_all")), 
       aes(x=disrate,y = E_V, color=group2, linetype=betakernel)) + 
  geom_line(size=1, position=position_jitter(w=0.02, h=0))+
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=4),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication()+
  theme(legend.title = element_blank(), legend.key.width=unit(2,"cm"))+
  guides(linetype=guide_legend(nrow  =4), colour=guide_legend(nrow=4,byrow=TRUE)) +
  labs(y = expression("viral encounters " ~ day^-1~cell^-1), x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

  
ggplot(data=allbetas.melt %>% filter(betakernel %in% c("beta_all")), 
       aes(x=disrate,y = E_V, color=group2)) + 
  geom_line(size=1, position=position_jitter(w=0.02, h=0))+
  geom_line(data = lith, aes(y= E_V, color=group2)) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication() +
  theme(legend.title = element_blank(), legend.key.width=unit(1,"cm"))+
  labs(y = expression("viral encounters " ~day^-1~cell^-1), x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

ggplot(data=allbetas.melt %>% filter(betakernel %in% c("beta_all")), 
       aes(x=disrate,y = E_HV, color=group2)) + 
  geom_line(size=1, position=position_jitter(w=0.02, h=0))+
  geom_line(data = lith, aes(y= E_HV, color=group2)) +
   scale_y_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=2),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  scale_x_log10(
        breaks = scales::trans_breaks("log10", function(x) 10^x, n=7),
        labels = scales::trans_format("log10", scales::math_format(10^.x))) +
  annotation_logticks()+
  theme_Publication() +
  theme(legend.title = element_blank(), legend.key.width=unit(1,"cm"))+
  labs(y = expression("viral encounters " ~ cm^-3~day^-1),x = expression("dissipation rate "~(m^2~s^-3))) +
  theme(legend.title = element_blank())

for saving just the R file

require (knitr)
purl(input = "D:/R program/Postdoc-R/R Notebook/Dec 2018/beta kernel 181204.Rmd") #output file will be on the main R directory and saved with the same file name


processing file: D:/R program/Postdoc-R/R Notebook/Dec 2018/beta kernel 181204.Rmd

  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |...                                                              |   5%
  |                                                                       
  |......                                                           |  10%
  |                                                                       
  |.........                                                        |  14%
  |                                                                       
  |............                                                     |  19%
  |                                                                       
  |...............                                                  |  24%
  |                                                                       
  |...................                                              |  29%
  |                                                                       
  |......................                                           |  33%
  |                                                                       
  |.........................                                        |  38%
  |                                                                       
  |............................                                     |  43%
  |                                                                       
  |...............................                                  |  48%
  |                                                                       
  |..................................                               |  52%
  |                                                                       
  |.....................................                            |  57%
  |                                                                       
  |........................................                         |  62%
  |                                                                       
  |...........................................                      |  67%
  |                                                                       
  |..............................................                   |  71%
  |                                                                       
  |..................................................               |  76%
  |                                                                       
  |.....................................................            |  81%
  |                                                                       
  |........................................................         |  86%
  |                                                                       
  |...........................................................      |  90%
  |                                                                       
  |..............................................................   |  95%
  |                                                                       
  |.................................................................| 100%
output file: beta kernel 181204.R
[1] "beta kernel 181204.R"
LS0tDQp0aXRsZTogImJldGEga2VybmVsIGZpbmFsIG5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2suIFdoZW4geW91IGV4ZWN1dGUgY29kZSB3aXRoaW4gdGhlIG5vdGVib29rLCB0aGUgcmVzdWx0cyBhcHBlYXIgYmVuZWF0aCB0aGUgY29kZS4gDQoNClRyeSBleGVjdXRpbmcgdGhpcyBjaHVuayBieSBjbGlja2luZyB0aGUgKlJ1biogYnV0dG9uIHdpdGhpbiB0aGUgY2h1bmsgb3IgYnkgcGxhY2luZyB5b3VyIGN1cnNvciBpbnNpZGUgaXQgYW5kIHByZXNzaW5nICpDdHJsK1NoaWZ0K0VudGVyKi4gDQoNCkFkZCBhIG5ldyBjaHVuayBieSBjbGlja2luZyB0aGUgKkluc2VydCBDaHVuayogYnV0dG9uIG9uIHRoZSB0b29sYmFyIG9yIGJ5IHByZXNzaW5nICpDdHJsK0FsdCtJKi4NCg0KV2hlbiB5b3Ugc2F2ZSB0aGUgbm90ZWJvb2ssIGFuIEhUTUwgZmlsZSBjb250YWluaW5nIHRoZSBjb2RlIGFuZCBvdXRwdXQgd2lsbCBiZSBzYXZlZCBhbG9uZ3NpZGUgaXQgKGNsaWNrIHRoZSAqUHJldmlldyogYnV0dG9uIG9yIHByZXNzICpDdHJsK1NoaWZ0K0sqIHRvIHByZXZpZXcgdGhlIEhUTUwgZmlsZSkuDQoNClRoZSBwcmV2aWV3IHNob3dzIHlvdSBhIHJlbmRlcmVkIEhUTUwgY29weSBvZiB0aGUgY29udGVudHMgb2YgdGhlIGVkaXRvci4gQ29uc2VxdWVudGx5LCB1bmxpa2UgKktuaXQqLCAqUHJldmlldyogZG9lcyBub3QgcnVuIGFueSBSIGNvZGUgY2h1bmtzLiBJbnN0ZWFkLCB0aGUgb3V0cHV0IG9mIHRoZSBjaHVuayB3aGVuIGl0IHdhcyBsYXN0IHJ1biBpbiB0aGUgZWRpdG9yIGlzIGRpc3BsYXllZC4NCg0KYGBge3J9DQpzZXR3ZCgiRDovUiBwcm9ncmFtIikNCiN2YWx1ZXMgbmVlZGVkIA0KDQpLPSAxLjM4MDY0ODUyKigxMCleLTIzICNtMiBrZy8gczIgSyBib2x0em1hbm4gY29uc3RhbnQNCm11PSAxLjEyNiooMTApXi0zICNrZy9tIHMgZHluYW1pYyB2aXNjb3NpdHkgaW4gMThDDQp2PSAxLjA5OSooMTApXi02ICNtMi9zIGtpbmVtYXRpYyB2aXNjb3NpdHkgaW4gMThDDQpSZWhfY2FsYz0gMi4zRS02ICNpbiBtIHJhZGl1cyBFaHV4DQpSZWhfbmFrZWQ9IDEuOEUtNiAjaW4gbSByYWRpdXMgRWh1eA0KUmVodj0gOTAqKDEwKV4tOSAjaW4gbSByYWRpdXMgdmlydXMNClRlbXAgPSAxOCsyNzMuMTUgI3RlbXAgaW4ga2VsdmluLCBoZXJlIGFzc3VtaW5nIDE4Qw0KRGVuX09jTSA9IDEuMDUgI2cvY20zIGRlbnNpdHkgb3JnYW5pYyBjZWxsIG1hdHRlcg0KRGVuX0NIMk89IDEuMDI1ICNnL2NtMyBkZW5zaXR5IHNlYXdhdGVyIGF0IDE4Qw0KaG9zdG51bSA8LSAoMTApXjMNCnZpcm51bSA8LSBob3N0bnVtKjUNCg0KcmVxdWlyZSAoZ2dwbG90MikNCnJlcXVpcmUocGxvdGx5KQ0KcmVxdWlyZShncmlkKQ0KcmVxdWlyZShnZ3RoZW1lcykNCnJlcXVpcmUgKGRwbHlyKQ0KcmVxdWlyZShwbHlyKQ0Kc291cmNlICgidGhlbWVfUHVibGljYXRpb24uUiIpDQpzb3VyY2UoInJlc2l6ZXdpbi5SIikNCiNyZXNpemUud2luKDEyLDkpDQpncmlkLm5ld3BhZ2UoKQ0KDQpgYGANCg0KZm9yIEJyb3duaWFuIG1vdGlvbg0KDQpgYGB7cn0NCiNCcm93bmlhbiBtb3Rpb24gKEJNKQ0KIzEuIG1ha2UgYSBkYXRhIGZyYW1lDQpCTSA8LSBkYXRhLmZyYW1lIChncm91cD0gYygibmFrZWQiLCAiY2FsY2lmaWVkIiksIHJhZD0gYygxLjhFLTYsIDIuM0UtNikpIA0KDQojMi4gY2FsY3VsYXRlIGJldGEgKGJldGEpDQpCTSRiZXRhX3MgPC0gKDIqKEsqKDEwKV40KSpUZW1wKigoKEJNJHJhZCtSZWh2KSoxMDApXjIpKS8oKDMqbXUqMTApKihCTSRyYWQqUmVodioxZTQpKSAjbTMvcw0KQk0kYmV0YV9kIDwtIEJNJGJldGFfcyo4NjQwMCAjdG8gY20zL2RheQ0KDQojIGdvIGJhY2sgdG8gdGhpcyBsYXRlcg0KIzMuIGNhbGN1bGF0ZSBlbmNvdW50ZXJzIChFKQ0KQk0kRSA8LSBCTSRiZXRhX2QqaG9zdG51bQ0KQk0kRV9IViA8LSBCTSRiZXRhX2QqdmlybnVtKmhvc3RudW0NCg0KQk0NCmBgYA0KDQpEaWZmZXJlbnRpYWwgc2V0dGxpbmcgKERTKQ0KDQpgYGB7cn0NCiNEaWZmZXJlbnRpYWwgc2V0dGxpbmcgKERTKQ0KIzEuIHJlYWQgaW4gUElDIGRhdGENCmxpYnJhcnkocmVhZHIpICNhbHdheXMgdXNlIHJlYWRyIG5vdCBiYXNlUg0KDQpzZXR3ZCgiRDovUiBwcm9ncmFtIikNClBJQyA8LSByZWFkX2NzdigiUG9zdGRvYy1SL0NTViBGaWxlcy9QSUMuY3N2IikNCg0KUElDJFN0cmFpbiA8LSBhcy5mYWN0b3IoUElDJFN0cmFpbikNClBJQyRSZXBsaWNhdGUgPC0gYXMuZmFjdG9yKFBJQyRSZXBsaWNhdGUpDQoNCiNjZXJ0YWluIGNoYW5nZXMgaW4gZGF0YS50YWJsZSBBUEkgbWFkZSBjYWxjdWxhdGluZyBpbnNpZGUgdGhlIGxpc3QgZGF0YS50YWJsZSB0byBub3Qgd29yaw0KDQojMi4gY2FsY3VsYXRlIFBJQw0KUElDJFBJQyA8LSBQSUMkVEMtUElDJEFDDQpQSUMkUElDcGVyY2VsbCA8LSAoUElDJFBJQy9QSUMkQ2VsbGNvdW50KSooMTApXi0zI2luIGcNClBJQyRQSUNwZXJjZWxscGcgPC0gUElDJFBJQ3BlcmNlbGwqMWUxMg0KUElDJFRDcGcgPC0gKFBJQyRUQy9QSUMkQ2VsbGNvdW50KSooMTApXi0zKjFlMTIgI3doYXQgaWYgdG90YWwgY2FyYm9uIGlzIHVzZWQgZm9yIGNhbGN1bGF0aW5nIGRlbnNpdHkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TdHJhaW4sIHk9UElDcGVyY2VsbHBnKSkgKyBnZW9tX2JveHBsb3QoKStnZW9tX3BvaW50KHNpemU9MikgK3RoZW1lX1B1YmxpY2F0aW9uKCkpDQpnZ3Bsb3RseShnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVN0cmFpbiwgeT1UQ3BnKSkgKyBnZW9tX2JveHBsb3QoKStnZW9tX3BvaW50KHNpemU9MikgK3RoZW1lX1B1YmxpY2F0aW9uKCkpDQoNCmBgYA0KDQpgYGB7cn0NCg0KIzMuIGNhbGN1bGF0ZSBkZW5zaXR5IG9mIGNlbGxzIChkZW4pDQpQSUMgPC0gbXV0YXRlKFBJQywgZ3JvdXAgPSBpZmVsc2UoUElDcGVyY2VsbHBnIDwgNCAsICJuYWtlZCIsICJjYWxjaWZpZWQiKSkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1ncm91cCwgeT1QSUNwZXJjZWxscGcpKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yLCBhZXMoY29sb3I9U3RyYWluKSkrDQogICAgICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkpDQoNClBJQyA8LSBtdXRhdGUoUElDLCByYWQgPSBpZmVsc2UoZ3JvdXAgPT0gIm5ha2VkIiAsICAxLjhFLTYsICAyLjNFLTYpKSAjaW4gbQ0KDQpQSUMkdm9sdW1lIDwtICg0LzMpKnBpKihQSUMkcmFkKjEwMCleMyAjaW4gY20zDQpQSUMkRGVuX2NlbGwyIDwtIChQSUMkVENwZyoxZS0xMikvUElDJHZvbHVtZSAjZy9jbTMsIGlmIFRDIGlzIHVzZWQgZGVuc2l0eSwgdG90YWwgZGVuc2l0eSAoYmVsb3cpIGJlY29tZXMgcmVhbGx5IGJpZyAoaS5lLiwgbWF4IDIgZy9jbTMgd2hpY2ggaXMgbm90IHJlYXNvbmFibGUpDQoNClBJQyREZW5fY2VsbCA8LSBQSUMkUElDcGVyY2VsbC9QSUMkdm9sdW1lICNnL2NtMw0KUElDJERlbl9jZWxsdG90YWwgPC0gUElDJERlbl9jZWxsK0Rlbl9PY00NCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TdHJhaW4sIHk9RGVuX2NlbGx0b3RhbCwgY29sb3I9Z3JvdXApKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yKSANCiAgICAgICAgICt0aGVtZV9QdWJsaWNhdGlvbigpKQ0KDQojc29tZSBzdHJhaW5zIHRoYXQgYXJlICJuYWtlZCIgaGF2ZSBQSUM8Mi4gSSBjaG9zZSB0byBpZ25vcmUgdGhpcyBzaW5jZSBpbiB0aGUgbG0gbW9kZWwgSSBkbyBub3QgdXNlDQojc3RyYWluIGFzIGEgZmFjdG9yLCByYXRoZXIgZGF0YSBpcyB0cmVhdGVkIGFzIGEgd2hvbGUgKGUuZy4sIG5vIGdyb3VwaW5nKQ0KDQojNC4gY2FsY3VsYXRlIHNpbmtpbmcgdmVsb2NpdHkgb2YgY2VsbHMNClBJQyRTaW5rVmVsIDwtICgoMiooKFBJQyRyYWQqMTAwKV4yKSooOTgxKSooUElDJERlbl9jZWxsdG90YWwtRGVuX0NIMk8pKS8oOSoobXUqMTApKSkqODY0ICNtZXRlciBwZXIgZGF5DQoNCiNnIGlzIGNvbnZlcnRlZCB0byBwZXIgZGF5LCA4NjQgaXMgdGhlIG9uZSB0aGF0IGNvbnZlcnRzIGNtL3MgdG8gbS9kYXkNCg0KI3Bsb3Qgc2lua2luZyB2ZWxvY2l0eSB2cyBjYWxjaWZpY2F0aW9uDQoNCmdncGxvdChkYXRhPVBJQywgYWVzKHg9UElDcGVyY2VsbHBnLCB5PVNpbmtWZWwsIGNvbG9yPVN0cmFpbiwgc2hhcGU9Z3JvdXApKSArIGdlb21fcG9pbnQoc2l6ZT01KSt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICAgIGxhYnMoeSA9IGV4cHJlc3Npb24oIlNpbmtpbmcgdmVsb2NpdHkifigibSJ+ZGF5Xi0xKSksIHggPSBleHByZXNzaW9uKCJQSUMifmNlbGxeLTEpKSArDQogICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj0yKSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKQ0KDQojNS4gY2FsY3VsYXRlIHNpbmt2ZWwgb2YgdmlydXNlcw0KDQpEZW5fdmlydXMgPC0gMS4wOSAjZGF0YSBmcm9tIEJlbiBELiBmcmVzaCBFaFYtMjA3IGRlbnNpdHkuIG9sZCBkZW5zaXR5IG9mIEVoVi0yMDcgaXMgMS4xOQ0KRWh2X1NpbmtWZWwgPC0gKCgyKigoUmVodioxMDApXjIpKig5ODEpKihEZW5fdmlydXMtRGVuX0NIMk8pKS8oOSoobXUqMTApKSkqODY0ICAjZXF1YWxzIHRvIDANCg0KIzYuIGNhbGN1bGF0ZSBiZXRhIGtlcm5lbHMNClBJQyRiZXRhX3MgPC0gcGkqKCgoUElDJHJhZCtSZWh2KSoxMDApXjIpKihhYnMoKFBJQyRTaW5rVmVsLUVodl9TaW5rVmVsKS84NjQpKSAjaW4gZW5jb3VudGVycyBjbTMvcw0KUElDJGJldGFfZCA8LSBQSUMkYmV0YV9zKjg2NDAwICNpbiBjbTMvZGF5DQoNClNpbmt2ZWxiZXRhLnBsb3Q8LSBnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVNpbmtWZWwsIHk9YmV0YV9kLCBjb2xvcj1TdHJhaW4sIHNoYXBlPWdyb3VwKSkgKyBnZW9tX3BvaW50KHNpemU9NSkrDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkrDQogIGxhYnMoeCA9IGV4cHJlc3Npb24oIlNpbmtpbmcgdmVsb2NpdHkifigibSJ+ZGF5Xi0xKSksIHkgPSBleHByZXNzaW9uKGJldGF+KCJFbmNvdW50ZXJzIiB+IGNtXjN+ZGF5Xi0xKSkpICsNCiBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpDQoNClNpbmt2ZWxiZXRhLnBsb3QgI2NoYW5nZSB0aWNrcw0KDQpnZ3Bsb3RseShTaW5rdmVsYmV0YS5wbG90KQ0KDQpnZ3Bsb3RseShnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVN0cmFpbiwgeT1TaW5rVmVsKSkgKyBnZW9tX2JveHBsb3QoKSt0aGVtZV9QdWJsaWNhdGlvbigpKQ0KDQpnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVBJQ3BlcmNlbGxwZywgeT1iZXRhX2QsIGNvbG9yPVN0cmFpbikpICsgZ2VvbV9wb2ludChzaXplPTUpK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oYmV0YX4oIkVuY291bnRlcnMifmNtXjN+ZGF5Xi0xKSksIHggPSBleHByZXNzaW9uKCJQSUMifmNlbGxeLTEpKSAgKw0Kc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj0yKSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKQ0KDQpgYGANCg0KYGBge3J9DQojNy4gY2FsY3VsYXRlIGJldGEgYW5kIGVuY291bnRlcnMNCiNiZXRhIGFyZSBpbiBjZWxscyBjbTMvIGRheSB0aGVuIGVuY291bnRlcnMgYXJlIHRvIGNlbGxzL2NtMyBkYXkNClBJQyRFX0RTX0hWIDwtIChQSUMkYmV0YV9kKnZpcm51bSpob3N0bnVtKSAgI0UgY2FsY3VsYXRlZCB3aXRoIFZpcnVzIGFuZCBIb3N0ICgxMDoxIE1PSSkNClBJQyRFX0RTX1YgPC0gKFBJQyRiZXRhX2QqdmlybnVtKSAjRSBjYWxjdWxhdGVkIHdpdGggVmlydXMNCg0KIzguIGNhbGN1bGF0ZSBmb3IgbGl0aCBwYXJhbWV0ZXJzDQoNCmxpdGh2b2wgPC0gMyoxZS0xMiAjaW4gY20zLCBmcm9tIENKJ3MgcGFwZXINClBJQyRwZXJsaXRoIDwtIFBJQyRQSUNwZXJjZWxsLzIwICNpbiBnLCBhc3N1bWluZyAyMCBsaXRocyBhdHRhY2hlZA0KUElDJHBlcmxpdGhwZyA8LSBQSUMkcGVybGl0aCoxZTEyICNpbiBwZw0KUElDJERlbmxpdGggPC0gKFBJQyRwZXJsaXRoL2xpdGh2b2wpICsgRGVuX09jTSAjaW4gZy9jbTMsIHdpdGggb3JnYW5pYyBtYXR0ZXIgYXR0YWNoZWQNCnJhZF9saXRoIDwtIDJFLTYgI2luIG0gcmFkaXVzDQoNClBJQyRTaW5rVmVsX2xpdGggPC0gKCgyKigocmFkX2xpdGgqMTAwKV4yKSooOTgxKSooUElDJERlbmxpdGgtRGVuX0NIMk8pKS8oOSoobXUqMTApKSkqODY0ICNtZXRlciBwZXIgZGF5DQpQSUMkYmV0YV9zX2xpdGggPC0gcGkqKCgocmFkX2xpdGgrUmVodikqMTAwKV4yKSooYWJzKChQSUMkU2lua1ZlbF9saXRoLUVodl9TaW5rVmVsKS84NjQpKSAjaW4gZW5jb3VudGVycyBjbTMvcw0KUElDJGJldGFfZF9saXRoIDwtIFBJQyRiZXRhX3NfbGl0aCo4NjQwMCAjaW4gY20zL2RheQ0KDQpnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PXBlcmxpdGhwZywgeT1TaW5rVmVsX2xpdGgsIGNvbG9yPVN0cmFpbiwgc2hhcGU9Z3JvdXApKSArIGdlb21fcG9pbnQoc2l6ZT01KSt0aGVtZV9QdWJsaWNhdGlvbigpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJTaW5raW5nIHZlbG9jaXR5In4oIm0ifmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5saXRoXi0xKSkgDQoNClBJQyRFbGl0aF9EU19IViA8LSAoUElDJGJldGFfZF9saXRoKnZpcm51bSpob3N0bnVtKSAgI0UgY2FsY3VsYXRlZCB3aXRoIFZpcnVzIGFuZCBIb3N0ICgxMDoxIE1PSSkNClBJQyRFbGl0aF9EU19WIDwtIChQSUMkYmV0YV9kX2xpdGgqdmlybnVtKSAjRSBjYWxjdWxhdGVkIHdpdGggVmlydXMNCg0KcmVxdWlyZSAoZHBseXIpDQoNClBJQyRncm91cDIgPC0gY2FzZV93aGVuKA0KICBQSUMkUElDcGVyY2VsbHBnIDwyICB+ICJuYWtlZF9ib3V5YW50IiwNCiAgUElDJFBJQ3BlcmNlbGxwZyA+MiAmIFBJQyRQSUNwZXJjZWxscGcgPCA0IH4gIm5ha2VkL2NhbGNpZmllZCB1bmNlcnRhaW4iLA0KICBQSUMkUElDcGVyY2VsbHBnID40ICYgUElDJFBJQ3BlcmNlbGxwZyA8IDEwIH4gIm1vZGVyYXRlbHkgY2FsY2lmaWVkIiwNCiAgUElDJFBJQ3BlcmNlbGxwZyA+MTAgfiAic3Ryb25nbHkgY2FsY2lmaWVkIiwgDQogIFRSVUUgfiBhcy5jaGFyYWN0ZXIoUElDJFBJQ3BlcmNlbGxwZykNCikNCg0KYnJlYWtzIDwtIDEwXigtMTA6MTApDQoNCmdncGxvdChkYXRhPVBJQywgYWVzKHg9U2lua1ZlbCwgeT1FX0RTX0hWLCBjb2xvcj1TdHJhaW4sIHNoYXBlPWdyb3VwKSkgKyBnZW9tX3BvaW50KHNpemU9NSkrdGhlbWVfUHVibGljYXRpb24oKSsNCiBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpDQoNCg0KZ2dwbG90KGRhdGE9UElDLCBhZXMoeD1TaW5rVmVsLCB5PUVfRFNfViwgY29sb3I9U3RyYWluLCBzaGFwZT1ncm91cCkpICsgZ2VvbV9wb2ludChzaXplPTUpK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49MiksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikNCg0KDQpnZ3Bsb3QoZGF0YT1QSUMsIGFlcyh4PVNpbmtWZWxfbGl0aCwgeT1FbGl0aF9EU19WLCBjb2xvcj1TdHJhaW4sIHNoYXBlPWdyb3VwKSkgKyBnZW9tX3BvaW50KHNpemU9NSkgKyANCiAgdGhlbWVfUHVibGljYXRpb24oKSArIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49MyksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikNCg0KDQoNCnN1bW1hcnlfRFMgPC0gZGRwbHkoUElDLCAuKFN0cmFpbiksIHN1bW1hcml6ZSwgIFBJQ3BlcmNlbGxwZz1tZWFuKFBJQ3BlcmNlbGxwZyksIHBlcmxpdGhwZyA9IG1lYW4ocGVybGl0aHBnKSwgDQogICAgICAgICAgICAgICAgICAgIERlbl9jZWxsdG90YWwgPSBtZWFuIChEZW5fY2VsbHRvdGFsKSwNCiAgICAgICAgICAgICAgICAgICAgU2lua1ZlbD1tZWFuKFNpbmtWZWwpLGJldGFfZD1tZWFuKGJldGFfZCksIEVfRFNfVj0gbWVhbihFX0RTX1YpLCBFX0RTX0hWPW1lYW4oRV9EU19IViksDQogICAgICAgICAgICAgICAgICAgIFNpbmtWZWxfbGl0aD1tZWFuIChTaW5rVmVsX2xpdGgpLCBiZXRhX2RfbGl0aD1tZWFuIChiZXRhX2RfbGl0aCksIEVsaXRoX0RTX0hWPW1lYW4gKEVsaXRoX0RTX0hWKSwNCiAgICAgICAgICAgICAgICAgICAgRWxpdGhfRFNfVj1tZWFuIChFbGl0aF9EU19WKSkNCg0Kc3VtbWFyeV9EU19ieWdyb3VwIDwtIGRkcGx5KFBJQywgLihncm91cDIpLCBzdW1tYXJpemUsICBQSUNwZXJjZWxscGc9bWVhbihQSUNwZXJjZWxscGcpLCBwZXJsaXRocGcgPSBtZWFuKHBlcmxpdGhwZyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlbl9jZWxsdG90YWwgPSBtZWFuIChEZW5fY2VsbHRvdGFsKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaW5rVmVsPW1lYW4oU2lua1ZlbCksYmV0YV9kPW1lYW4oYmV0YV9kKSwgRV9EU19WPSBtZWFuKEVfRFNfViksIEVfRFNfSFY9bWVhbihFX0RTX0hWKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgU2lua1ZlbF9saXRoPW1lYW4gKFNpbmtWZWxfbGl0aCksIGJldGFfZF9saXRoPW1lYW4gKGJldGFfZF9saXRoKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRWxpdGhfRFNfSFY9bWVhbiAoRWxpdGhfRFNfSFYpLCBFbGl0aF9EU19WPW1lYW4gKEVsaXRoX0RTX1YpKQ0KDQpzdW1tYXJ5X0RTDQpzdW1tYXJ5X0RTX2J5Z3JvdXANCg0Kc2V0d2QoIkQ6L1IgcHJvZ3JhbSIpDQpyZXF1aXJlKG9wZW54bHN4KQ0Kd3JpdGUueGxzeChzdW1tYXJ5X0RTLCBmaWxlID0gIlBvc3Rkb2MtUi9FeHBvcnRlZCBUYWJsZXMvc3VtbWFyeV9EUy54bHN4IikNCndyaXRlLnhsc3goc3VtbWFyeV9EU19ieWdyb3VwLCBmaWxlID0gIlBvc3Rkb2MtUi9FeHBvcnRlZCBUYWJsZXMvc3VtbWFyeV9EU19ieWdyb3VwLnhsc3giKQ0KDQpgYGANCg0KYGBge3J9DQoNCiM5LiByZWdyZXNzaW9uIG9mIFBJQyBhbmQgc2lua3ZlbCBvZiBjZWxscyBhbmQgbGl0aHMNCg0KI2EuIGZvciBjZWxscw0KUElDX3JlZyA8LSBsbShTaW5rVmVsflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpICNlc3NlbnRpYWxseSBwZXJmZWN0IGZpdDogc3VtbWFyeSBtYXkgYmUgdW5yZWxpYWJsZSBoYWhhDQpzdW1tYXJ5KFBJQ19yZWcpDQpwbG90KHJlc2lkdWFscy5sbShQSUNfcmVnKSkNCmxheW91dChtYXRyaXgoMTo0LDIsMikpDQpwbG90KFBJQ19yZWcpDQoNCmNvZWYoUElDX3JlZykNCiMgY29lZihQSUNfcmVnKQ0KIyhJbnRlcmNlcHQpIFBJQ3BlcmNlbGxwZyANCiMwLjAxODAwODUyICAgMC4wMTc3NDc2NCANCg0KY29yKFBJQyRQSUNwZXJjZWxscGcsIFBJQyRTaW5rVmVsKQ0KI2NvciA9IDAuOTk4OTA0Mg0KDQpiZXRhX3JlZyA8LSBsbShiZXRhX2R+UElDcGVyY2VsbHBnLCBkYXRhPVBJQykNCnBsb3QocmVzaWR1YWxzLmxtKGJldGFfcmVnKSkNCmNvZWYoYmV0YV9yZWcpDQojY29lZihiZXRhX3JlZykNCiMgKEludGVyY2VwdCkgUElDcGVyY2VsbHBnIA0KIzEuNjM5MjMzZS0wNyAzLjI0MzA1NGUtMDcNCg0KRV9EU19IVl9yZWcgPC0gbG0oRV9EU19IVn5QSUNwZXJjZWxscGcsIGRhdGE9UElDKQ0KRV9EU19WX3JlZyA8LSBsbShFX0RTX1Z+UElDcGVyY2VsbHBnLCBkYXRhPVBJQykNCnBsb3QocmVzaWR1YWxzLmxtKEVfRFNfSFZfcmVnKSkNCnBsb3QocmVzaWR1YWxzLmxtKEVfRFNfVl9yZWcpKQ0KY29lZihFX0RTX0hWX3JlZykNCmNvZWYoRV9EU19WX3JlZykNCg0KI2IuIGZvciBsaXRocw0KcGVybGl0aF9yZWcgPC0gbG0gKHBlcmxpdGhwZ35QSUNwZXJjZWxscGcsIGRhdGE9UElDKQ0KcGxvdChyZXNpZChwZXJsaXRoX3JlZykpDQpjb2VmKHBlcmxpdGhfcmVnKQ0Kc2lua3ZlbF9saXRoX3JlZyA8LSBsbShTaW5rVmVsX2xpdGh+UElDcGVyY2VsbHBnLCBkYXRhID0gUElDKQ0Kc3VtbWFyeShzaW5rdmVsX2xpdGhfcmVnKQ0KcGxvdChyZXNpZHVhbHMubG0oc2lua3ZlbF9saXRoX3JlZykpDQpsYXlvdXQobWF0cml4KDE6NCwyLDIpKQ0KcGxvdChzaW5rdmVsX2xpdGhfcmVnKQ0KY29lZihzaW5rdmVsX2xpdGhfcmVnKQ0KDQpiZXRhX2xpdGhfcmVnIDwtIGxtKGJldGFfZF9saXRoflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpDQpwbG90KHJlc2lkdWFscy5sbShiZXRhX2xpdGhfcmVnKSkNCmNvZWYoYmV0YV9saXRoX3JlZykNCg0KRWxpdGhfRFNfSFZfcmVnIDwtIGxtKEVsaXRoX0RTX0hWflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpDQpFbGl0aF9EU19WX3JlZyA8LSBsbShFbGl0aF9EU19WflBJQ3BlcmNlbGxwZywgZGF0YT1QSUMpDQpwbG90KHJlc2lkdWFscy5sbShFbGl0aF9EU19IVl9yZWcpKQ0KcGxvdChyZXNpZHVhbHMubG0oRWxpdGhfRFNfVl9yZWcpKQ0KY29lZihFbGl0aF9EU19IVl9yZWcpDQpjb2VmKEVsaXRoX0RTX1ZfcmVnKQ0KDQpgYGANCg0KYGBge3J9DQoNCiMgOS4gbWFrZSBuZXcgZGF0YWZyYW1lIGRlcGVuZGluZyBvbiBleHBlcmltZW50YWwgUElDIHZhbHVlcw0KIyBtYWtlIGEgcHJlZGljdGlvbiBiYXNlZCBvbiBQSUMgdmFsdWVzDQpyZXF1aXJlKHRydW5jbm9ybSkNCnJlcXVpcmUoUm1pc2MpDQpzdW1tYXJ5KFBJQyRQSUNwZXJjZWxscGcpDQpzdW1tYXJ5U0UoZGF0YT1QSUMsIG1lYXN1cmV2YXI9IlBJQ3BlcmNlbGxwZyIpDQpQSUNfbmV3ZGF0YSA8LSBhcy5kYXRhLmZyYW1lKHJ0cnVuY25vcm0obj0xMDAwLCBhPS0xLjYsIGI9MjAuMTQsIG1lYW49NC43LCBzZD02LjE1KSkNCg0KI3JlbmFtZSBjb2x1bW4uIHJlbmFtZSBmdW5jdGlvbiBpbiBwbHlyIA0KbGlicmFyeShwbHlyKQ0KUElDX25ld2RhdGEgPC0gcmVuYW1lIChQSUNfbmV3ZGF0YSwgYyAoInJ0cnVuY25vcm0obiA9IDEwMDAsIGEgPSAtMS42LCBiID0gMjAuMTQsIG1lYW4gPSA0LjcsIHNkID0gNi4xNSkiID0gDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQSUNwZXJjZWxscGciKSkNCg0KUElDX25ld2RhdGEgPC0gbXV0YXRlKFBJQ19uZXdkYXRhLCBncm91cCA9IGlmZWxzZShQSUNwZXJjZWxscGcgPCA0ICwgIm5ha2VkIiwgImNhbGNpZmllZCIpKQ0KDQpnZ3Bsb3RseShnZ3Bsb3QoZGF0YT1QSUNfbmV3ZGF0YSwgYWVzKHg9Z3JvdXAsIHk9UElDcGVyY2VsbHBnKSkgKyBnZW9tX2JveHBsb3QoKStnZW9tX3BvaW50KHNpemU9MikgKw0KICAgICAgICAgICB0aGVtZV9QdWJsaWNhdGlvbigpKQ0KDQpQSUNfbmV3ZGF0YSRncm91cDIgPC0gY2FzZV93aGVuKA0KICBQSUNfbmV3ZGF0YSRQSUNwZXJjZWxscGcgPDIgIH4gIm5ha2VkX2JvdXlhbnQiLA0KICBQSUNfbmV3ZGF0YSRQSUNwZXJjZWxscGcgPjIgJiBQSUNfbmV3ZGF0YSRQSUNwZXJjZWxscGcgPCA0IH4gIm5ha2VkL2NhbGNpZmllZCB1bmNlcnRhaW4iLA0KICBQSUNfbmV3ZGF0YSRQSUNwZXJjZWxscGcgPjQgJiBQSUNfbmV3ZGF0YSRQSUNwZXJjZWxscGcgPCAxMCB+ICJtb2RlcmF0ZWx5IGNhbGNpZmllZCIsDQogIFBJQ19uZXdkYXRhJFBJQ3BlcmNlbGxwZyA+MTAgfiAic3Ryb25nbHkgY2FsY2lmaWVkIiwgDQogIFRSVUUgfiBhcy5jaGFyYWN0ZXIoUElDX25ld2RhdGEkUElDcGVyY2VsbHBnKQ0KKQ0KDQpQSUNfbmV3ZGF0YSRncm91cDIgPC0gZmFjdG9yIChQSUNfbmV3ZGF0YSRncm91cDIsbGV2ZWxzPSBjKCJuYWtlZF9ib3V5YW50IiwgIm5ha2VkL2NhbGNpZmllZCB1bmNlcnRhaW4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtb2RlcmF0ZWx5IGNhbGNpZmllZCIsICJzdHJvbmdseSBjYWxjaWZpZWQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJuYWtlZCIsICJuYWtlZC9jYWxjaWZpZWQgdW5jZXJ0YWluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtb2RlcmF0ZWx5IGNhbGNpZmllZCIsICJzdHJvbmdseSBjYWxjaWZpZWQiKSkNCg0KZ2dwbG90bHkoZ2dwbG90KGRhdGE9UElDX25ld2RhdGEsIGFlcyh4PWdyb3VwMiwgeT1QSUNwZXJjZWxscGcpKSArIGdlb21fYm94cGxvdCgpK2dlb21fcG9pbnQoc2l6ZT0yKQ0KICAgICAgICAgK3RoZW1lX1B1YmxpY2F0aW9uKCkpDQoNCiNhLiBmb3IgaG9zdA0KUElDX25ld2RhdGEkU2lua1ZlbC5wcmVkIDwtIHByZWRpY3QoUElDX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQpQSUNfbmV3ZGF0YV9yZWcgPC0gbG0oU2lua1ZlbC5wcmVkflBJQ3BlcmNlbGxwZywgZGF0YT1QSUNfbmV3ZGF0YSkgDQpjb2VmKFBJQ19uZXdkYXRhX3JlZykNCiNzYW1lIGNvZWYgYXMgUElDX3JlZw0KIz4gY29lZihQSUNfbmV3ZGF0YV9yZWcpDQojKEludGVyY2VwdCkgUElDcGVyY2VsbHBnIA0KIzAuMDE4MDA4NTIgICAwLjAxNzc0NzY0IA0KDQpwbG90KHJlc2lkKFBJQ19uZXdkYXRhX3JlZykpDQoNCmdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9U2lua1ZlbC5wcmVkKSkgK2dlb21fcG9pbnQoc2l6ZT0yKSArdGhlbWVfUHVibGljYXRpb24oKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigiUHJlZGljdGVkIFNpbmtpbmcgdmVsb2NpdHkifigibSJ+ZGF5Xi0xKSksIHggPSBleHByZXNzaW9uKCJQSUMifmNlbGxeLTEpKSANCg0KUElDX25ld2RhdGEkYmV0YS5wcmVkIDwtIHByZWRpY3QoYmV0YV9yZWcsIGRhdGEuZnJhbWUoUElDX25ld2RhdGEpKQ0KUElDX25ld2RhdGEkRV9EU19WLnByZWQgPC0gcHJlZGljdChFX0RTX1ZfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNClBJQ19uZXdkYXRhJEVfRFNfSFYucHJlZCA8LSBwcmVkaWN0KEVfRFNfSFZfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNCg0KZ2dwbG90KGRhdGE9UElDX25ld2RhdGEsIGFlcyh4PVBJQ3BlcmNlbGxwZywgeT1FX0RTX1YucHJlZCkpICtnZW9tX3BvaW50KHNpemU9NSwgYWVzKGNvbG9yPWdyb3VwMikpICsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgZ2VvbV9zbW9vdGgoKSArDQogICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKSArDQogICAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gZGF5Xi0xfmNlbGxeLTEpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5jZWxsXi0xKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNCmdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9RV9EU19IVi5wcmVkKSkgK2dlb21fcG9pbnQoc2l6ZT01LCBhZXMoY29sb3I9Z3JvdXAyKSkgKw0KICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyBnZW9tX3Ntb290aCgpICsNCiAgICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpICsNCiAgICBsYWJzKHkgPSBleHByZXNzaW9uKCJ2aXJhbCBlbmNvdW50ZXJzICIgfiBjbV4tM35kYXleLTEpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5jZWxsXi0xKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNClBJQ2JldGFfbmV3IDwtIGdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1QSUNwZXJjZWxscGcsIHk9YmV0YS5wcmVkKSkgKw0KICBnZW9tX3BvaW50KHNpemU9NSwgYWVzKGNvbG9yPVBJQ3BlcmNlbGxwZykpKw0KICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQobmFtZT0iUElDIiwgZ3VpZGU9Z3VpZGVfY29sb3JiYXIoZGlyZWN0aW9uID0gInZlcnRpY2FsIiwgYmFyaGVpZ2h0PTEwKSkrDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyANCiAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKSArDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oYmV0YX4oIlByZWRpY3RlZCBFbmNvdW50ZXJzIn5jbV4zfmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5jZWxsXi0xKSkrDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpDQpQSUNiZXRhX25ldw0KDQojYi4gZm9yIGxpdGhzDQpQSUNfbmV3ZGF0YSRwZXJsaXRocGcucHJlZCA8LSBwcmVkaWN0KHBlcmxpdGhfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNClBJQ19uZXdkYXRhJFNpbmtWZWwucHJlZC5saXRoIDwtIHByZWRpY3Qoc2lua3ZlbF9saXRoX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQpzaW5rdmVsX2xpdGhfcmVnLnByZWQgPC0gbG0oU2lua1ZlbC5wcmVkLmxpdGh+UElDcGVyY2VsbHBnLCBkYXRhPVBJQ19uZXdkYXRhKSANCmNvZWYoc2lua3ZlbF9saXRoX3JlZy5wcmVkKQ0KI3NhbWUgY29lZiBhcyBzaW5rdmVsX2xpdGhfcmVnDQojPiBjb2VmKHNpbmt2ZWxfbGl0aF9yZWcucHJlZCkNCiMoSW50ZXJjZXB0KSBQSUNwZXJjZWxscGcgDQojIDAuMDE2NzI3NTMgICAwLjAxMTE1MTY5IA0KDQpwbG90KHJlc2lkKHNpbmt2ZWxfbGl0aF9yZWcucHJlZCkpDQoNCmdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1wZXJsaXRocGcucHJlZCwgeT1TaW5rVmVsLnByZWQubGl0aCkpICtnZW9tX3BvaW50KHNpemU9MikgK3RoZW1lX1B1YmxpY2F0aW9uKCkrDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oIlByZWRpY3RlZCBTaW5raW5nIHZlbG9jaXR5IG9mIExpdGhzIn4oIm0ifmRheV4tMSkpLCB4ID0gZXhwcmVzc2lvbigiUElDIn5saXRoXi0xKSkgDQoNClBJQ19uZXdkYXRhJGJldGEucHJlZC5saXRoIDwtIHByZWRpY3QoYmV0YV9saXRoX3JlZywgZGF0YS5mcmFtZShQSUNfbmV3ZGF0YSkpDQpQSUNfbmV3ZGF0YSRFX0RTX1YucHJlZC5saXRoIDwtIHByZWRpY3QoRWxpdGhfRFNfSFZfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNClBJQ19uZXdkYXRhJEVfRFNfSFYucHJlZC5saXRoIDwtIHByZWRpY3QoRWxpdGhfRFNfSFZfcmVnLCBkYXRhLmZyYW1lKFBJQ19uZXdkYXRhKSkNCg0KZ2dwbG90KGRhdGE9UElDX25ld2RhdGEsIGFlcyh4PVBJQ3BlcmNlbGxwZywgeT1FX0RTX1YucHJlZC5saXRoKSkgK2dlb21fcG9pbnQoc2l6ZT01LCBhZXMoY29sb3I9Z3JvdXAyKSkgKw0KICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyBnZW9tX3Ntb290aCgpICsNCiAgICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcz0ibCIpICsNCiAgICBsYWJzKHkgPSBleHByZXNzaW9uKCJ2aXJhbCBlbmNvdW50ZXJzICIgfiBkYXleLTF+Y2VsbF4tMSksIHggPSBleHByZXNzaW9uKCJQSUMifmxpdGheLTEpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KZ2dwbG90KGRhdGE9UElDX25ld2RhdGEsIGFlcyh4PVBJQ3BlcmNlbGxwZywgeT1FX0RTX0hWLnByZWQubGl0aCkpICtnZW9tX3BvaW50KHNpemU9NSwgYWVzKGNvbG9yPWdyb3VwMikpICsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgZ2VvbV9zbW9vdGgoKSArDQogICAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXM9ImwiKSArDQogICAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gY21eLTN+ZGF5Xi0xKSwgeCA9IGV4cHJlc3Npb24oIlBJQyJ+bGl0aF4tMSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQpQSUNiZXRhX25ldy5saXRoIDwtIGdncGxvdChkYXRhPVBJQ19uZXdkYXRhLCBhZXMoeD1wZXJsaXRocGcucHJlZCwgeT1iZXRhLnByZWQubGl0aCkpICsNCiAgZ2VvbV9wb2ludChzaXplPTUsIGFlcyhjb2xvcj1QSUNwZXJjZWxscGcpKSsNCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50KG5hbWU9IlBJQyIsIGd1aWRlPWd1aWRlX2NvbG9yYmFyKGRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsIGJhcmhlaWdodD0xMCkpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpICsgDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKyBhbm5vdGF0aW9uX2xvZ3RpY2tzKHNpZGVzPSJsIikgKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKGJldGF+KCJQcmVkaWN0ZWQgRW5jb3VudGVycyBvZiBsaXRoICIgfmNtXjN+ZGF5Xi0xKSksIHggPSBleHByZXNzaW9uKCJQSUMifmxpdGheLTEpKSsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikNClBJQ2JldGFfbmV3LmxpdGgNCg0KI3N1bW1hcmllcw0Kc3VtbWFyeV9EU19uZXdkYXRhX2J5Z3JvdXAyIDwtIGRkcGx5KFBJQ19uZXdkYXRhLCAuKGdyb3VwMiksIHN1bW1hcml6ZSwgIFBJQ3BlcmNlbGxwZz1tZWFuKFBJQ3BlcmNlbGxwZyksIFNpbmtWZWwucHJlZD1tZWFuKFNpbmtWZWwucHJlZCksYmV0YS5wcmVkPSBtZWFuIChiZXRhLnByZWQpLCBFX0RTX1YucHJlZD0gbWVhbihFX0RTX1YucHJlZCksIEVfRFNfSFYucHJlZD1tZWFuKEVfRFNfSFYucHJlZCkpDQoNCnN1bW1hcnlfRFNfYnlncm91cC5wcmVkIDwtIGRkcGx5KFBJQ19uZXdkYXRhLCAuKGdyb3VwMiksIHN1bW1hcml6ZSwgIFBJQ3BlcmNlbGxwZz1tZWFuKFBJQ3BlcmNlbGxwZyksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlcmxpdGhwZy5wcmVkID0gbWVhbihwZXJsaXRocGcucHJlZCksIFNpbmtWZWwucHJlZD1tZWFuKFNpbmtWZWwucHJlZCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYmV0YS5wcmVkPSBtZWFuIChiZXRhLnByZWQpLCBFX0RTX1YucHJlZD0gbWVhbihFX0RTX1YucHJlZCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIEVfRFNfSFYucHJlZD1tZWFuKEVfRFNfSFYucHJlZCksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNpbmtWZWwucHJlZC5saXRoPW1lYW4oU2lua1ZlbC5wcmVkLmxpdGgpLGJldGEucHJlZC5saXRoPSBtZWFuIChiZXRhLnByZWQubGl0aCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgRV9EU19WLnByZWQubGl0aD0gbWVhbihFX0RTX1YucHJlZC5saXRoKSwgRV9EU19IVi5wcmVkLmxpdGg9bWVhbihFX0RTX0hWLnByZWQubGl0aCkpDQoNCnN1bW1hcnlfRFNfYnlncm91cC5wcmVkDQoNCndyaXRlLnhsc3goc3VtbWFyeV9EU19ieWdyb3VwLnByZWQsIGZpbGUgPSAiUG9zdGRvYy1SL0V4cG9ydGVkIFRhYmxlcy9zdW1tYXJ5X0RTX2J5Z3JvdXAucHJlZC54bHN4IikNCg0KDQpgYGANCg0KdHVyYnVsZW5jZQ0KDQpgYGB7cn0NCiNUVVJCVUxFTkNFDQojZGlzcmF0ZSBpcyBjbTIvczMNCg0KI21ha2UgZGF0YSBmcmFtZQ0KDQpkaXNyYXRlIDwtIHJlcF9sZW4oMTBeKC04Oi0yKSwgbGVuZ3RoLm91dD0xNCkNCmNhbGMgPC0gcmVwX2xlbihjKCJjYWxjaWZpZWQiKSwgbGVuZ3RoLm91dD03KQ0KbmFrZWQgPC0gcmVwX2xlbihjKCJuYWtlZCIpLCBsZW5ndGgub3V0PTcpDQpsaXRoIDwtIHJlcF9sZW4oYygibGl0aCIpLCBsZW5ndGgub3V0PTcpDQpncm91cCA8LSBjKGNhbGMsIG5ha2VkLCBsaXRoKQ0KdHVyYiA8LSBhcy5kYXRhLmZyYW1lKGNiaW5kKGRpc3JhdGUsIGdyb3VwKSkNCg0KdHVyYiRyYWQgPC0gY2FzZV93aGVuKA0KICAgIHR1cmIkZ3JvdXAgPT0ibmFrZWQiIH4gMS44RS02LA0KICAgIHR1cmIkZ3JvdXAgPT0iY2FsY2lmaWVkIiB+IDIuM0UtNiwNCiAgICB0dXJiJGdyb3VwID09ImxpdGgiIH4gMkUtNiwNCiAgICBUUlVFIH4gYXMubnVtZXJpYyh0dXJiJGdyb3VwKQ0KKQ0KI3R1cmIgPC0gbXV0YXRlKHR1cmIsIHJhZCA9IGlmZWxzZShncm91cCA9PSAibmFrZWQiICwgIDEuOEUtNiwgIDIuM0UtNikpICNpbiBtDQoNCnR1cmIkZGlzcmF0ZSA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0dXJiJGRpc3JhdGUpKQ0KDQp0dXJiJEtvbCA8LSAoKHZeMy90dXJiJGRpc3JhdGUpXjAuMjUpKjEwMCAjS29sbW9nb3JvdiBsZW5ndGggc2NhbGUgaW4gY20NCiNldmVyeXRoaW5nIGlzIGJlbG93IDEgY20sIHVzZSBlcW4gMiBpbiBUSyANCg0KdHVyYiRiZXRhX2QgPC0gKDQuMipwaSooKHR1cmIkZGlzcmF0ZS8odioxMDBeMikpXjAuNSkqKCgodHVyYiRyYWQrUmVodikqMTAwKV4zKSkqODY0MDAgDQoNCnR1cmIkYmV0YV9IZWlkaSA8LSAoMC40MipwaSooKHR1cmIkZGlzcmF0ZS8odioxMDBeMikpXjAuNSkqKCgodHVyYiRyYWQrUmVodikqMTAwKV4zKSkqODY0MDANCg0KI2NoZWNrIGVuY291bnRlcnMNCg0KI3VzZSBUSywgaW4gY20zIHMNCnR1cmIkRV90dXJiX0hWIDwtICh0dXJiJGJldGFfZCpob3N0bnVtKnZpcm51bSkgI0UgY2FsY3VsYXRlZCB3aXRoIFZpcnVzIGFuZCBIb3N0ICgxMDoxIE1PSSkNCnR1cmIkRV90dXJiX1YgPC0gKHR1cmIkYmV0YV9kKnZpcm51bSkgI0UgY2FsY3VsYXRlZCB3aXRoIHZpcnVzIG9ubHkNCg0KI2JyZWFrcyA8LSAxMF4oLTEwOjEwKQ0KI21pbm9yX2JyZWFrcyA8LSByZXAoMTo5LCAyMSkqKDEwXnJlcCgtMTA6MTAsIGVhY2g9OSkpDQoNCmdncGxvdChkYXRhID0gdHVyYiwgYWVzKHggPSBkaXNyYXRlLCB5ID0gYmV0YV9kLCBjb2xvcj1ncm91cCkpICsgZ2VvbV9wb2ludChzaXplID01KSArDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgYW5ub3RhdGlvbl9sb2d0aWNrcygpICsNCiAgdGhlbWVfUHVibGljYXRpb24oKSArDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oYmV0YX4oInByZWRpY3RlZCBlbmNvdW50ZXJzICIgfmNtXjN+ZGF5Xi0xKSksIA0KICAgICAgIHggPSBleHByZXNzaW9uKCJkaXNzaXBhdGlvbiByYXRlICJ+KG1eMn5zXi0zKSkpICsNCiAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCiAgDQoNCmxpYnJhcnkoc2NhbGVzKQ0KDQpnZ3Bsb3QoZGF0YSA9IHR1cmIsIGFlcyh4ID0gZGlzcmF0ZSwgeSA9IEVfdHVyYl9WLCBjb2xvcj1ncm91cCkpICsgZ2VvbV9wb2ludChzaXplID01KSArDQogICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gZGF5Xi0xfmNlbGxeLTEpLCB4ID0gZXhwcmVzc2lvbigiZGlzc2lwYXRpb24gcmF0ZSAifihtXjJ+c14tMykpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCg0KZ2dwbG90KGRhdGEgPSB0dXJiLCBhZXMoeCA9IGRpc3JhdGUsIHkgPSBFX3R1cmJfSFYsIGNvbG9yPWdyb3VwKSkgKyBnZW9tX3BvaW50KHNpemUgPTUpICsNCiAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgYW5ub3RhdGlvbl9sb2d0aWNrcygpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJ2aXJhbCBlbmNvdW50ZXJzICIgfiBjbV4tM35kYXleLTEpLHggPSBleHByZXNzaW9uKCJkaXNzaXBhdGlvbiByYXRlICJ+KG1eMn5zXi0zKSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQpgYGANCg0KYWRkIGJldGEga2VybmVscyBhbmQgcGxvdA0KDQpgYGB7cn0NCiNleHRyYWN0IG1lYW4gYmV0YXMgZnJvbSBQSUNfbmV3ZGF0YQ0KYmV0YV9EUyA8LSBzdW1tYXJ5U0UgKFBJQ19uZXdkYXRhLCBtZWFzdXJldmFyID0gImJldGEucHJlZCIsIGdyb3VwdmFycyA9IGMoImdyb3VwIiwgImdyb3VwMiIpKQ0KbGl0aF9EUyA8LXN1bW1hcnlTRSAoUElDX25ld2RhdGEsIG1lYXN1cmV2YXIgPSAiYmV0YS5wcmVkLmxpdGgiLCBncm91cHZhcnMgPSBjKCJncm91cCIsICJncm91cDIiKSkNCg0KbGl0aF9EUyRncm91cDEgPC0gbGl0aF9EUyRncm91cA0KbGl0aF9EUyRncm91cCA8LSAibGl0aCINCg0KI3NlcGFyYXRlIGRhdGEgZnJhbWVzIGZvciBob3N0IGFuZCBsaXRocw0KDQphbGwgPC0gUmVkdWNlKGZ1bmN0aW9uKHgseSkgbWVyZ2UoeCx5LGJ5PSJncm91cCIsYWxsPVRSVUUpICwNCiAgICAgICAgICAgICAgbGlzdChCTSwgYmV0YV9EUywgdHVyYiAlPiUgZmlsdGVyKGdyb3VwICVpbiUgYygibmFrZWQiLCAiY2FsY2lmaWVkIikpKSkNCg0KDQphbGwubGl0aHMgIDwtIFJlZHVjZShmdW5jdGlvbih4LHkpIG1lcmdlKHgseSxieT0iZ3JvdXAiLGFsbD1UUlVFKSAsDQogICAgICAgICAgICAgICAgICAgICBsaXN0KGxpdGhfRFMsIHR1cmIgJT4lIGZpbHRlcihncm91cCAlaW4lIGMoImxpdGgiKSkpKQ0KDQojYmV0YV9kLng9Qk0sIGJldGEucHJlZD1EUywgYmV0YXByZWQubGl0aD0gYmV0YS5wcmVkLmxpdGgsIGJldGFfZC55PXR1cmINCg0KI3JlbmFtZSBiZXRhLnByZWQgdG8gYmV0YV9wcmVkIHNvIEkgY2FuIHVzZSBncmVwLiANCiNhbGwgPC0gcmVuYW1lIChhbGwsIGMoImJldGFfZC54IiA9ICJiZXRhX0JNIiwgImJldGEucHJlZCIgPSAiYmV0YV9EUyIsICJiZXRhX2QueSIgPSAiYmV0YV90dXJiIikpDQoNCmxpYnJhcnkoZGF0YS50YWJsZSkNCk5UID0gZGF0YS50YWJsZShhbGwsIGtleT0iZ3JvdXAyIikNCmFsbGJldGFzID0gTlRbLCBsaXN0KGdyb3VwPWdyb3VwLCBkaXNyYXRlPWRpc3JhdGUsIGJldGFfQk09YmV0YV9kLngsIGJldGFfRFM9YmV0YS5wcmVkLCBiZXRhX3R1cmIgPSBiZXRhX2QueSwgDQogICAgICAgICAgICAgICAgICAgICBiZXRhX0JNX0RTID1iZXRhX2QueCArIGJldGEucHJlZCwNCiAgICAgICAgICAgICAgICAgICAgIGJldGFfRFNfdHVyYiA9IGJldGEucHJlZCArIGJldGFfZC55LA0KICAgICAgICAgICAgICAgICAgICAgYmV0YV9CTV90dXJiID0gYmV0YV9kLnggKyBiZXRhX2QueSwNCiAgICAgICAgICAgICAgICAgICAgIGJldGFfYWxsID0gYmV0YV9kLnggKyBiZXRhX2QueSArIGJldGEucHJlZCksIA0KICAgICAgICAgICAgICBieT1jKCJncm91cDIiKV0NCg0KTlQyIDwtIGRhdGEudGFibGUoYWxsLmxpdGhzLCBrZXkgPSAiZ3JvdXAyIikNCmFsbGJldGFzLmxpdGggPSBOVDJbLCBsaXN0KGdyb3VwPWdyb3VwLCBncm91cDE9Z3JvdXAxLCBkaXNyYXRlPWRpc3JhdGUsIGJldGFfRFMubGl0aD1iZXRhLnByZWQubGl0aCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIGJldGFfdHVyYi5saXRoID0gYmV0YV9kLCANCiAgICAgICAgICAgICAgICAgICAgIGJldGFfRFNfdHVyYi5saXRoID1iZXRhLnByZWQubGl0aCArIGJldGFfZCksIA0KICAgICAgICAgICAgICAgICAgICAgYnk9YygiZ3JvdXAyIildDQoNCmdncGxvdChhbGxiZXRhcywgYWVzKGRpc3JhdGUsIHkgPSB2YWx1ZSwgY29sb3I9Z3JvdXAyKSkgKyANCiAgICBnZW9tX2xpbmUoYWVzKHkgPSBiZXRhX0RTX3R1cmIsIGxpbmV0eXBlID0gIkRTK3R1cmIiKSwgc2l6ZT0xKSArIA0KICAgIGdlb21fbGluZShhZXMoeSA9IGJldGFfYWxsLCBsaW5ldHlwZSA9ICJCTStEUyt0dXJiIiksIHNpemU9MSkrDQogICAgZ2VvbV9saW5lKGFlcyh5ID0gYmV0YV90dXJiLCBsaW5ldHlwZSA9ICJ0dXJiIiksIHNpemU9MSkrDQogICAgZ2VvbV9saW5lKGRhdGEgPSBhbGxiZXRhcy5saXRoLCBhZXMoeT0gYmV0YV9EU190dXJiLmxpdGgsIGxpbmV0eXBlPSJEUyt0dXJiLmxpdGgiKSkgKw0KICAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICAgIHNjYWxlX3hfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NyksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICAgIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsNCiAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkud2lkdGg9dW5pdCgyLCJjbSIpKSsNCiAgICBndWlkZXMobGluZXR5cGU9Z3VpZGVfbGVnZW5kKG5yb3cgID00KSwgY29sb3VyPWd1aWRlX2xlZ2VuZChucm93PTQsYnlyb3c9VFJVRSkpIA0KDQpnZ3Bsb3QoYWxsYmV0YXMsIGFlcyhkaXNyYXRlLCB5ID0gdmFsdWUsIGNvbG9yPWdyb3VwMikpICsgDQogIGdlb21fbGluZShhZXMoeSA9IGJldGFfRFNfdHVyYiwgbGluZXR5cGUgPSAiRFMrdHVyYiIpLCBzaXplPTEpICsgDQogIGdlb21fbGluZShkYXRhID0gYWxsYmV0YXMubGl0aCwgYWVzKHk9IGJldGFfRFNfdHVyYi5saXRoLCBsaW5ldHlwZT0iRFMrdHVyYi5saXRoIikpICsgDQogIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTcpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgYW5ub3RhdGlvbl9sb2d0aWNrcygpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5LndpZHRoPXVuaXQoMiwiY20iKSkrDQogIGd1aWRlcyhsaW5ldHlwZT1ndWlkZV9sZWdlbmQobnJvdyAgPTQpLCBjb2xvdXI9Z3VpZGVfbGVnZW5kKG5yb3c9NCxieXJvdz1UUlVFKSkgDQoNCiNlbmNvdW50ZXJzDQoNCiNtZWx0IGRhdGENCg0KYWxsYmV0YXMubWVsdCA8LSBtZWx0IChhbGxiZXRhcywgaWQudmFycyA9IGMoImdyb3VwMiIsICJncm91cCIsICJkaXNyYXRlIiksIHZhbHVlLm5hbWUgPSAiYmV0YV9kIiwgDQogICAgICAgICAgICAgICAgICAgICAgIHZhcmlhYmxlLm5hbWUgPSAiYmV0YWtlcm5lbCIpDQoNCmFsbGJldGFzLm1lbHQkRV9WIDwtIGFsbGJldGFzLm1lbHQkYmV0YV9kKnZpcm51bQ0KYWxsYmV0YXMubWVsdCRFX0hWIDwtIGFsbGJldGFzLm1lbHQkYmV0YV9kKnZpcm51bSpob3N0bnVtDQoNCmFsbGJldGFzLm1lbHQubGl0aCA8LSBtZWx0IChhbGxiZXRhcy5saXRoLCBpZC52YXJzID0gYygiZ3JvdXAyIiwgImdyb3VwMSIsICJncm91cCIsICJkaXNyYXRlIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLm5hbWUgPSAiYmV0YV9kIiwgdmFyaWFibGUubmFtZSA9ICJiZXRha2VybmVsIikNCg0KYWxsYmV0YXMubWVsdC5saXRoJEVfViA8LSBhbGxiZXRhcy5tZWx0LmxpdGgkYmV0YV9kKnZpcm51bQ0KYWxsYmV0YXMubWVsdC5saXRoJEVfSFYgPC0gYWxsYmV0YXMubWVsdC5saXRoJGJldGFfZCp2aXJudW0qaG9zdG51bQ0KDQpnZ3Bsb3QoYWxsYmV0YXMubWVsdCwgYWVzKGRpc3JhdGUsIHkgPSBFX1YsIGNvbG9yPWdyb3VwMikpICsgDQogIGdlb21fbGluZShzaXplPTEpKw0KICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj03KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSArIGZhY2V0X2dyaWQofmJldGFrZXJuZWwpDQoNCiNzdWJzZXQgZGF0YQ0KDQpncmFwaDEgPC0gc3Vic2V0KGFsbGJldGFzLm1lbHQsIGJldGFrZXJuZWwgJWluJSBjICgiYmV0YV9CTSIsICJiZXRhX0RTIiwgImJldGFfQk1fRFMiKSkNCmdyYXBoMiA8LSBzdWJzZXQoYWxsYmV0YXMubWVsdCwgYmV0YWtlcm5lbCAlaW4lIGMgKCJiZXRhX3R1cmIiLCAiYmV0YV9EU190dXJiIiwgImJldGFfQk1fdHVyYiIsICJiZXRhX2FsbCIpKQ0KbGl0aCA8LSBzdWJzZXQoYWxsYmV0YXMubWVsdC5saXRoLCBiZXRha2VybmVsICVpbiUgYygiYmV0YV9EU190dXJiLmxpdGgiKSAmIGdyb3VwMSAlaW4lIGMoImNhbGNpZmllZCIpKQ0KbGl0aCRtYWluZ3JvdXAgPC0gbGl0aCRncm91cDINCmxpdGgkZ3JvdXAyIDwtIGFzLmZhY3RvcihwYXN0ZShsaXRoJG1haW5ncm91cCwgbGl0aCRncm91cCwgc2VwPSctJykpDQoNCmdncGxvdChncmFwaDEsIGFlcyhncm91cDIsIHkgPSBFX1YsIGNvbG9yPWJldGFrZXJuZWwpKSArIA0KICBnZW9tX2ppdHRlcihzaXplPTUpKw0KICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTQpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgYW5ub3RhdGlvbl9sb2d0aWNrcyhzaWRlcyA9ICJsIikrDQogIHRoZW1lX1B1YmxpY2F0aW9uKCkgKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJ2aXJhbCBlbmNvdW50ZXJzICIgfiBkYXleLTF+Y2VsbF4tMSkpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQ0KDQpncmFwaDEuc3VtIDwtIHN1bW1hcnlTRSAoZ3JhcGgxLCBtZWFzdXJldmFyID0gIkVfViIsIGdyb3VwdmFycyA9IGMoImJldGFrZXJuZWwiLCAiZ3JvdXAyIikpDQoNCmdncGxvdChncmFwaDEuc3VtLCBhZXMoZ3JvdXAyLCB5ID0gRV9WLCBjb2xvcj1iZXRha2VybmVsKSkgKyANCiAgZ2VvbV9wb2ludChzaXplPTUsICBwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgwLjIpKSsNCiAgc2NhbGVfeV9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj00KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3Moc2lkZXMgPSAibCIpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpICsNCiAgbGFicyh5ID0gZXhwcmVzc2lvbigidmlyYWwgZW5jb3VudGVycyAiIH4gZGF5Xi0xfmNlbGxeLTEpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkNCiAgDQpnZ3Bsb3QoZGF0YT1hbGxiZXRhcy5tZWx0ICU+JSBmaWx0ZXIoYmV0YWtlcm5lbCAlaW4lIGMoImJldGFfdHVyYiIsICJiZXRhX2FsbCIpKSwgDQogICAgICAgYWVzKHg9ZGlzcmF0ZSx5ID0gRV9WLCBjb2xvcj1ncm91cDIsIGxpbmV0eXBlPWJldGFrZXJuZWwpKSArIA0KICBnZW9tX2xpbmUoc2l6ZT0xLCBwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXIodz0wLjAyLCBoPTApKSsNCiAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49NCksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTcpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgYW5ub3RhdGlvbl9sb2d0aWNrcygpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksIGxlZ2VuZC5rZXkud2lkdGg9dW5pdCgyLCJjbSIpKSsNCiAgZ3VpZGVzKGxpbmV0eXBlPWd1aWRlX2xlZ2VuZChucm93ICA9NCksIGNvbG91cj1ndWlkZV9sZWdlbmQobnJvdz00LGJ5cm93PVRSVUUpKSArDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oInZpcmFsIGVuY291bnRlcnMgIiB+IGRheV4tMX5jZWxsXi0xKSwgeCA9IGV4cHJlc3Npb24oImRpc3NpcGF0aW9uIHJhdGUgIn4obV4yfnNeLTMpKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQogIA0KZ2dwbG90KGRhdGE9YWxsYmV0YXMubWVsdCAlPiUgZmlsdGVyKGJldGFrZXJuZWwgJWluJSBjKCJiZXRhX2FsbCIpKSwgDQogICAgICAgYWVzKHg9ZGlzcmF0ZSx5ID0gRV9WLCBjb2xvcj1ncm91cDIpKSArIA0KICBnZW9tX2xpbmUoc2l6ZT0xLCBwb3NpdGlvbj1wb3NpdGlvbl9qaXR0ZXIodz0wLjAyLCBoPTApKSsNCiAgZ2VvbV9saW5lKGRhdGEgPSBsaXRoLCBhZXMoeT0gRV9WLCBjb2xvcj1ncm91cDIpKSArDQogICBzY2FsZV95X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTIpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgc2NhbGVfeF9sb2cxMCgNCiAgICAgICAgYnJlYWtzID0gc2NhbGVzOjp0cmFuc19icmVha3MoImxvZzEwIiwgZnVuY3Rpb24oeCkgMTBeeCwgbj03KSwNCiAgICAgICAgbGFiZWxzID0gc2NhbGVzOjp0cmFuc19mb3JtYXQoImxvZzEwIiwgc2NhbGVzOjptYXRoX2Zvcm1hdCgxMF4ueCkpKSArDQogIGFubm90YXRpb25fbG9ndGlja3MoKSsNCiAgdGhlbWVfUHVibGljYXRpb24oKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLmtleS53aWR0aD11bml0KDEsImNtIikpKw0KICBsYWJzKHkgPSBleHByZXNzaW9uKCJ2aXJhbCBlbmNvdW50ZXJzICIgfmRheV4tMX5jZWxsXi0xKSwgeCA9IGV4cHJlc3Npb24oImRpc3NpcGF0aW9uIHJhdGUgIn4obV4yfnNeLTMpKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNCg0KZ2dwbG90KGRhdGE9YWxsYmV0YXMubWVsdCAlPiUgZmlsdGVyKGJldGFrZXJuZWwgJWluJSBjKCJiZXRhX2FsbCIpKSwgDQogICAgICAgYWVzKHg9ZGlzcmF0ZSx5ID0gRV9IViwgY29sb3I9Z3JvdXAyKSkgKyANCiAgZ2VvbV9saW5lKHNpemU9MSwgcG9zaXRpb249cG9zaXRpb25faml0dGVyKHc9MC4wMiwgaD0wKSkrDQogIGdlb21fbGluZShkYXRhID0gbGl0aCwgYWVzKHk9IEVfSFYsIGNvbG9yPWdyb3VwMikpICsNCiAgIHNjYWxlX3lfbG9nMTAoDQogICAgICAgIGJyZWFrcyA9IHNjYWxlczo6dHJhbnNfYnJlYWtzKCJsb2cxMCIsIGZ1bmN0aW9uKHgpIDEwXngsIG49MiksDQogICAgICAgIGxhYmVscyA9IHNjYWxlczo6dHJhbnNfZm9ybWF0KCJsb2cxMCIsIHNjYWxlczo6bWF0aF9mb3JtYXQoMTBeLngpKSkgKw0KICBzY2FsZV94X2xvZzEwKA0KICAgICAgICBicmVha3MgPSBzY2FsZXM6OnRyYW5zX2JyZWFrcygibG9nMTAiLCBmdW5jdGlvbih4KSAxMF54LCBuPTcpLA0KICAgICAgICBsYWJlbHMgPSBzY2FsZXM6OnRyYW5zX2Zvcm1hdCgibG9nMTAiLCBzY2FsZXM6Om1hdGhfZm9ybWF0KDEwXi54KSkpICsNCiAgYW5ub3RhdGlvbl9sb2d0aWNrcygpKw0KICB0aGVtZV9QdWJsaWNhdGlvbigpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQua2V5LndpZHRoPXVuaXQoMSwiY20iKSkrDQogIGxhYnMoeSA9IGV4cHJlc3Npb24oInZpcmFsIGVuY291bnRlcnMgIiB+IGNtXi0zfmRheV4tMSkseCA9IGV4cHJlc3Npb24oImRpc3NpcGF0aW9uIHJhdGUgIn4obV4yfnNeLTMpKSkgKw0KICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpDQoNCmBgYA0KDQpmb3Igc2F2aW5nIGp1c3QgdGhlIFIgZmlsZQ0KYGBge3J9DQpyZXF1aXJlIChrbml0cikNCnB1cmwoaW5wdXQgPSAiRDovUiBwcm9ncmFtL1Bvc3Rkb2MtUi9SIE5vdGVib29rL0RlYyAyMDE4L2JldGEga2VybmVsIDE4MTIwNC5SbWQiKSAjb3V0cHV0IGZpbGUgd2lsbCBiZSBvbiB0aGUgbWFpbiBSIGRpcmVjdG9yeSBhbmQgc2F2ZWQgd2l0aCB0aGUgc2FtZSBmaWxlIG5hbWUNCmBgYA0KDQpgYGB7cn0NCg0KDQoNCmBgYA0KDQo=